import { _decorator, CCInteger, Component, UITransform, Canvas, animation, v2, Node, find, Vec3 } from 'cc';
const { ccclass, property } = _decorator;
import { Joystick } from "./Joystick";
import { eventTarget, GameEvent } from '../Events/EventBus';


@ccclass('PlayerControl')
export class PlayerControl extends Component {



    @property(CCInteger)
    private speed: number = 100;
    @property(CCInteger)
    private MapWidth: number = 1280;
    @property(CCInteger)
    private MapHeight: number = 720;
    // 静止状态阈值
    @property
    stationaryThreshold: number = 0.01;


    private stick: Joystick = null;

    private realPlayerWidth: number = 0;
    private realPlayerHeight: number = 0;
    private playerAnchorPointX: number = 0.5;
    private playerAnchorPointY: number = 0.5;


    private siblingIndex = 0;
    private parentChildren: Node[] = [];
    private yPos: number = 0;


    // 角色移动方向
    private walkDir: number = 0;

    // 存储上一帧的位置
    private previousPosition: Vec3 = new Vec3();
    // 判断是否静止状态
    private isStationary: boolean = true;
    // 添加静止帧计数器用来判断角色静止
    private stationaryFrames: number = 0;
    private framesToConfirmStationary: number = 5; // 连续多少帧静止才确认为静止状态

    // private playerAnimationController: animation.AnimationController | null = null;

    protected onLoad(): void {
        //获取角色的相较父节点Canvas场景的缩放比例
        const scaleX = this.node.scale.x;
        const scaleY = this.node.scale.y;
        //获取角色节点的UITransform中的Size内容尺寸
        const PlayerTransform = this.node.getComponent(UITransform);
        if (PlayerTransform) {
            //获取内容尺寸（Size类型）
            const contentSize = PlayerTransform.contentSize;
            //获取宽度
            var playerWidth = contentSize.width;
            //获取高度
            var playerHeight = contentSize.height;

            //获取角色UITransform的AnchorPoint锚点位置用于后续地图边界计算坐标时x，y要乘上对应的AnchorPoint的值
            //这样进行坐标比对的时候才是和默认(0.5 , 0.5)用实际角色尺寸宽高一半的源代码效果一致
            this.playerAnchorPointX = PlayerTransform.anchorX;
            this.playerAnchorPointY = PlayerTransform.anchorY;
        }
        //根据角色节点的UITransform中的内容尺寸来计算在父节点Canvas中的实际大小。
        this.realPlayerWidth = playerWidth * scaleX;
        this.realPlayerHeight = playerHeight * scaleY;

        const stickNode = find("Canvas/UIRoot/Joystick");
        this.stick = stickNode.getComponent(Joystick);

        // 记录玩家起始位置
        Vec3.copy(this.previousPosition, this.node.position);

    }

    start() {
        this.parentChildren = this.node.parent.children;
        //获取玩家美术子节点的动画控制组件
        // this.playerAnimationController = this.node.getChildByName("character_femaleAdventurer").getComponent(animation.AnimationController);
    }


    update(deltaTime: number) {

        //获取动画图中变量Walk控制移动动画
        // let walkDir = animationController.getValue("Walk");

        // 计算当前位置与上一帧位置的差异
        const currentPosition = this.node.position;
        const movement = Vec3.distance(currentPosition, this.previousPosition);

        // 判断是否静止
        if(movement < this.stationaryThreshold){
            this.stationaryFrames++;

            // 连续多帧静止才确认为静止状态
            if(this.stationaryFrames >= this.framesToConfirmStationary && !this.isStationary){
                this.isStationary = true;
                eventTarget.emit(GameEvent.Player_Idle);
            }
        }else {
            // 有移动，重置计数器
            if(this.isStationary){
                // 有移动修改静止状态判断变量
                this.isStationary = false;
                
            }
            this.stationaryFrames = 0;
        }

        // 更新上一帧位置
        Vec3.copy(this.previousPosition, currentPosition);

        //获取玩家目前位置坐标
        var oldx = this.node.position.x;
        var oldy = this.node.position.y;
        // 当x坐标未变时，设置动画图中变量Idle的值为true，即角色不移动时处于Idle待机动画。
        // this.playerAnimationController.setValue("Idle", true);

        if (this.stick.dir.length() < 0.5) {
            return;
        }
        var vx = this.speed * this.stick.dir.x;
        var vy = this.speed * this.stick.dir.y;
        var sx = vx * deltaTime;
        var sy = vy * deltaTime;
        var newx = this.node.position.x + sx;
        var newy = this.node.position.y + sy;
        let halfMapWidth = this.MapWidth / 2;
        let halfMapHeight = this.MapHeight / 2;

        //实际是乘以AnchorPoint锚点位置的(x,y)对应坐标的比率
        //所以将x,y边界判断都加上了AnchorPoint的参与，使得该代码在不同Size和不同AnchorPoint的玩家节点均能通用
        //同样比较x时，即判断左右边界，也应该乘上对应的比率
        //所以比较地图左边界时要乘以playerAnchorPointX
        let leftPlayerWidth = this.realPlayerWidth * this.playerAnchorPointX;
        //比较地图右边界时要乘以( 1 - playerAnchorPointX )
        let rightPlayerWidth = this.realPlayerWidth * (1 - this.playerAnchorPointX);
        //因为rpg项目中玩家Player1的锚点位置的y修改为了，0.1,那么它基于锚点的上下比例就变成9:1
        //所以比较地图下边界时是乘以0.1，即playerAnchorPointY
        let downPlayerHeight = this.realPlayerHeight * this.playerAnchorPointY;
        //比较上边界时则是乘以（1 - playerAnchorPointY)
        let upPlayerHeight = this.realPlayerHeight * (1 - this.playerAnchorPointY);

        //限定角色移动的地图边界
        if (newx - leftPlayerWidth < -halfMapWidth) {         //左边界
            newx = -halfMapWidth + leftPlayerWidth;
        } else if (newx + rightPlayerWidth > halfMapWidth) {    //右边界
            newx = halfMapWidth - rightPlayerWidth;
        }
        if (newy - downPlayerHeight < -halfMapHeight) {       //下边界
            newy = -halfMapHeight + downPlayerHeight;
        } else if (newy + upPlayerHeight > halfMapHeight) {  //上边界
            newy = halfMapHeight - upPlayerHeight;
        }


        //通过判断新x坐标和旧x坐标差值判断移动方向s
        if (newx - oldx > 0) {
            this.walkDir = 1;
            eventTarget.emit(GameEvent.Player_Move, this.walkDir);
            // this.playerAnimationController.setValue("Idle", false);
            // this.playerAnimationController.setValue("WalkDir", 1);
        } else if (newx - oldx < 0) {
            this.walkDir = -1;
            eventTarget.emit(GameEvent.Player_Move, this.walkDir);         
            // this.playerAnimationController.setValue("Idle", false);
            // this.playerAnimationController.setValue("WalkDir", -1);
        }
   

        // 用于测试运动方向是否正确console.log(animationController.getValue("WalkDir"));
        
        // 更新玩家位置
        this.node.setPosition(newx, newy);

        // 判断角色当前角色位置的x值和y值和存储上一次的x，y的值是否相等，只有相等时说明角色未移动
        // 此时派发角色静止待机Idle事件
        // if(newx == oldx && newy == oldy){
        //     // eventTarget.emit(GameEvent.Player_Idle);
            
        //     this.playerAnimationController.setValue("Idle", true);
        // }

        // // 判断移动后玩家节点位置的x坐标是否有变化，有变化就派发移动事件，并更新xPos
        // if(this.node.position.x != this.xPos){
        //     this.xPos = this.node.position.x;
        // }

        //判断玩家节点目前y坐标和用来存储判断遮挡关系节点次序的yPos是否有变化
        //有变化再调用更改遮挡次序函数changeShelter，并将新的y坐标赋值给yPos
        if (this.node.position.y != this.yPos) {
            this.changeShelter();
            this.yPos = this.node.position.y;
        }


    }

    changeShelter() {
        let stillShelter = true;
        let count = 0;
        do {//获取当前节点的位次
            count++
            //用count限制循环总次数，避免循环数过大，超过10次后break一下
            //后面角色再移动，需要调用changeShelter时再将count重置为0
            if (count > 10) {
                break;
            }
            this.siblingIndex = this.node.getSiblingIndex();
            // console.log('当前节点的位次：' + this.siblingIndex);
            //定义前后节点位次
            let prevIndex = this.siblingIndex - 1;
            let nextIndex = this.siblingIndex + 1;
            //判断前后节点是否存在
            let prevNode = this.parentChildren[prevIndex];
            let nextNode = this.parentChildren[nextIndex];

            if (prevNode) {
                const prevNodeYPos = prevNode.position.y;
                //如果前节点y坐标小于角色y坐标，则交换位置
                if (prevNodeYPos < this.yPos) {
                    this.node.setSiblingIndex(prevIndex);
                    continue;
                }
            }
            if (nextNode) {
                const nextNodeYPos = nextNode.position.y;
                //如果后节点y坐标大于角色y坐标，则交换位置
                if (nextNodeYPos > this.yPos) {
                    this.node.setSiblingIndex(nextIndex);
                    continue;
                }
            }
            //如果未触发交换位置，则说明当前节点已经是最佳位置，终止循环
            stillShelter = false;

        } while (stillShelter);
    }


}


